<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>全屏填充式放大镜效果</title>
    <style>
        .container {
            display: flex;
            gap: 30px;
            padding: 20px;
            background: #f8f8f8;
        }

        /* 原图容器（充满模式） */
        .original-box {
            width: 576px;
            height: 576px;
            border: 2px solid #ddd;
            position: relative;
            overflow: hidden;
            background: #000;
        }

        .original-box img {
            width: 100%;
            height: 100%;
            object-fit: cover; /* 关键修改：图片充满容器 */
            cursor: crosshair;
        }

        /* 放大镜遮罩 */
        .magnifier-lens {
            position: absolute;
            background: rgba(255, 255, 255, 0.3);
            border: 2px solid #fff;
            box-shadow: 0 0 10px rgba(0,0,0,0.3);
            pointer-events: none;
            opacity: 0;
            transition: opacity 0.15s;
        }

        /* 放大图容器 */
        .zoomed-box {
            width: 576px;
            height: 576px;
            border: 2px solid #ddd;
            overflow: hidden;
            position: relative;
            background: #000;
        }

        .zoomed-image {
            position: absolute;
            will-change: transform;
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="original-box" id="originalBox">
            <img src="./img/GitHub头像.jpg" alt="原图" id="sourceImg">
            <div class="magnifier-lens" id="lens"></div>
        </div>
        <div class="zoomed-box" id="zoomedBox">
            <img src="./img/GitHub头像.jpg" alt="放大图" class="zoomed-image" id="zoomedImg">
        </div>
    </div>

    <script>
        // 配置参数
        const CONFIG = {
            zoomLevel: 2,        // 放大倍数
            lensSize: 150,       // 遮罩尺寸（正方形）
            transition: 0.1      // 过渡时间
        };

        // 元素引用
        const originalBox = document.getElementById('originalBox');
        const sourceImg = document.getElementById('sourceImg');
        const lens = document.getElementById('lens');
        const zoomedBox = document.getElementById('zoomedBox');
        const zoomedImg = document.getElementById('zoomedImg');

        // 运行时变量
        let imgData = {
            naturalWidth: 0,
            naturalHeight: 0,
            scaleRatio: 1,
            offsetX: 0,
            offsetY: 0
        };
        let isReady = false;

        // 初始化图片数据
        const initImageData = () => {
            const img = new Image();
            img.src = sourceImg.src;
            
            img.onload = () => {
                // 获取原始尺寸
                imgData.naturalWidth = img.naturalWidth;
                imgData.naturalHeight = img.naturalHeight;

                // 计算实际显示比例
                const containerRatio = originalBox.offsetWidth / originalBox.offsetHeight;
                const imageRatio = imgData.naturalWidth / imgData.naturalHeight;

                // 计算缩放比例和偏移量
                if (imageRatio > containerRatio) {
                    // 宽度超出，上下裁剪
                    imgData.scaleRatio = originalBox.offsetHeight / imgData.naturalHeight;
                    imgData.offsetX = (originalBox.offsetWidth - imgData.naturalWidth * imgData.scaleRatio) / 2;
                    imgData.offsetY = 0;
                } else {
                    // 高度超出，左右裁剪
                    imgData.scaleRatio = originalBox.offsetWidth / imgData.naturalWidth;
                    imgData.offsetY = (originalBox.offsetHeight - imgData.naturalHeight * imgData.scaleRatio) / 2;
                    imgData.offsetX = 0;
                }

                // 设置遮罩层尺寸
                lens.style.width = `${CONFIG.lensSize}px`;
                lens.style.height = `${CONFIG.lensSize}px`;

                // 设置大图尺寸
                zoomedImg.style.width = `${imgData.naturalWidth * CONFIG.zoomLevel}px`;
                zoomedImg.style.height = `${imgData.naturalHeight * CONFIG.zoomLevel}px`;

                isReady = true;
            };
        };

        // 鼠标移动处理
        const handleMouseMove = (e) => {
            if (!isReady) return;

            // 获取容器位置
            const boxRect = originalBox.getBoundingClientRect();
            
            // 计算鼠标在原始图片上的坐标
            let imgX = (e.clientX - boxRect.left - imgData.offsetX) / imgData.scaleRatio;
            let imgY = (e.clientY - boxRect.top - imgData.offsetY) / imgData.scaleRatio;

            // 边界限制
            imgX = Math.max(0, Math.min(imgX, imgData.naturalWidth));
            imgY = Math.max(0, Math.min(imgY, imgData.naturalHeight));

            // 计算遮罩位置
            const lensX = (imgX * imgData.scaleRatio) + imgData.offsetX - CONFIG.lensSize/2;
            const lensY = (imgY * imgData.scaleRatio) + imgData.offsetY - CONFIG.lensSize/2;

            // 更新遮罩位置
            lens.style.left = `${lensX}px`;
            lens.style.top = `${lensY}px`;
            lens.style.opacity = '1';

            // 计算大图位置
            const bgX = -imgX * CONFIG.zoomLevel + zoomedBox.offsetWidth/2;
            const bgY = -imgY * CONFIG.zoomLevel + zoomedBox.offsetHeight/2;

            // 应用边界限制
            const maxX = (imgData.naturalWidth * CONFIG.zoomLevel) - zoomedBox.offsetWidth;
            const maxY = (imgData.naturalHeight * CONFIG.zoomLevel) - zoomedBox.offsetHeight;
            const finalX = Math.max(-maxX, Math.min(bgX, 0));
            const finalY = Math.max(-maxY, Math.min(bgY, 0));

            zoomedImg.style.transform = `translate(${finalX}px, ${finalY}px)`;
        };

        // 鼠标离开处理
        const handleMouseLeave = () => {
            lens.style.opacity = '0';
        };

        // 初始化
        initImageData();
        originalBox.addEventListener('mousemove', handleMouseMove);
        originalBox.addEventListener('mouseleave', handleMouseLeave);

        // 窗口重置监听
        window.addEventListener('resize', () => {
            isReady = false;
            initImageData();
        });
    </script>
</body>
</html>